package tools;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Stack;

import core.DrawContext;
import core.DrawTool;
import core.VectorialObject;

public class BucketFillTool extends DrawTool {

	private Color color = Color.black;
	
	private Cursor cursor = Cursor.getDefaultCursor();
	
	@Override
	public void processKeyEvent(KeyEvent evt, DrawContext context) {
		// TODO Auto-generated method stub

	}

	@Override
	public void processMouseEvent(MouseEvent evt, DrawContext context) {

		switch(evt.getID()){
		case MouseEvent.MOUSE_CLICKED:
			
			Color target = new Color(context.getImage().getRGB(evt.getX(), evt.getY()));
			
			fill(evt.getX(), evt.getY(), context, target, color);
			
			context.setChanged(true);
			
			break;
			
		case MouseEvent.MOUSE_MOVED:
			configureMouseIcon(evt, context, cursor);
			break;
		}

	}
	
	public Cursor getCursor() {
		return cursor;
	}

	public void setCursor(Cursor cursor) {
		this.cursor = cursor;
	}

	private void fill(int x, int y, DrawContext ctx , Color targetColor, Color replacement){
		
		Stack<Point> stack = new Stack<Point>();
		
		BufferedImage image = ctx.getImage();
		
		if(image.getRGB(x, y) != targetColor.getRGB()){
			return;
		}
		
		stack.push(new Point(x,y));
		
		int w, e;
		
		Shape bounds;
		
		if(ctx.hasSelection()){
			bounds = ctx.getSelectionShape();
		}
		else{
			bounds = new Rectangle2D.Double(0, 0, image.getWidth(), image.getHeight());
		}
		
		while(!stack.empty()){
		
			Point node = stack.pop();
	
			w = (int) node.getX() - 1;
			
			Point currentP = new Point();
			
			currentP.x = (int) node.getX() + 1;
			
			currentP.y = (int) node.getY();
			
			while(bounds.contains(currentP)){
				
				if(image.getRGB((int)currentP.getX(), (int)currentP.getY()) != targetColor.getRGB()) break;
					
				image.setRGB((int)currentP.getX(), (int)currentP.getY(), replacement.getRGB());
				
				Point southNode = new Point((int)currentP.getX(), (int) currentP.getY() + 1);
				if(bounds.contains(southNode)){
					stack.push(southNode);
				}
				
				Point northNode = new Point((int)currentP.getX(), (int) currentP.getY() - 1);
				if(bounds.contains(northNode)){
					stack.push(northNode);
				}
				
				currentP.x++;
			}

			currentP.x = (int) node.getX() - 1;
			
			currentP.y = (int) node.getY();
			
			
			while(bounds.contains(currentP)){
				
				if(image.getRGB((int)currentP.getX(), (int)currentP.getY()) != targetColor.getRGB()) break;
					
				image.setRGB((int)currentP.getX(), (int)currentP.getY(), replacement.getRGB());
				
				Point southNode = new Point((int)currentP.getX(), (int) currentP.getY() + 1);
				if(bounds.contains(southNode)){
					stack.push(southNode);
				}
				
				Point northNode = new Point((int)currentP.getX(), (int) currentP.getY() - 1);
				if(bounds.contains(northNode)){
					stack.push(northNode);
				}
				
				currentP.x--;
			}
			
			
		}
		
	}

	public Color getColor() {
		return color;
	}

	public void setColor(Color color) {
		this.color = color;
	}

	@Override
	public void dispose(DrawContext ctx) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void init(DrawContext ctx) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSelection(VectorialObject vo) {
		// TODO Auto-generated method stub
		
	}
	
}
